package com.hongyi.system.controller;

import cn.dev33.satoken.annotation.SaCheckPermission;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import com.github.xiaoymin.knife4j.annotations.ApiSort;
import com.hongyi.common.excel.core.ExcelListener;
import com.hongyi.common.excel.core.ExcelResult;
import com.hongyi.common.excel.utils.ExcelUtil;
import com.hongyi.common.framework.constant.UserConstans;
import com.hongyi.common.framework.domain.JsonResult;
import com.hongyi.common.framework.utils.ServletUtils;
import com.hongyi.common.framework.utils.StreamUtils;
import com.hongyi.common.framework.utils.common.ArrayUtils;
import com.hongyi.common.framework.utils.common.ObjectUtils;
import com.hongyi.common.framework.validate.AddGroup;
import com.hongyi.common.framework.validate.EditGroup;
import com.hongyi.common.framework.validate.PasswordAuthGroup;
import com.hongyi.common.framework.validate.StatusGroup;
import com.hongyi.common.log.annotation.Log;
import com.hongyi.common.log.enums.BusinessType;
import com.hongyi.common.mybatis.page.PageData;
import com.hongyi.common.mybatis.page.PageQuery;
import com.hongyi.common.saToken.utils.LoginUtils;
import com.hongyi.common.web.controller.BaseController;
import com.hongyi.system.domain.SysRole;
import com.hongyi.system.domain.SysUser;
import com.hongyi.system.domain.dto.SysPostDto;
import com.hongyi.system.domain.dto.SysRoleDto;
import com.hongyi.system.domain.dto.SysUserDto;
import com.hongyi.system.domain.vo.*;
import com.hongyi.system.listener.SysUserImportListener;
import com.hongyi.system.service.ISysPostService;
import com.hongyi.system.service.ISysRoleService;
import com.hongyi.system.service.ISysUserService;
import com.hongyi.system.service.impl.SysUserServiceImpl;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.BeanUtils;
import org.springframework.http.MediaType;
import org.springframework.util.StopWatch;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 用户信息
 *
 * @author DingHao
 */
@ApiSort(value = 10)
@Api(tags = "用户信息接口")
@Validated
@RestController
@RequestMapping("/system/user")
public class SysUserController extends BaseController {

    @Autowired
    private ISysUserService sysUserService;

    @Autowired
    private ISysRoleService sysRoleService;

    @Autowired
    private ISysPostService sysPostService;

    /**
     * 获取用户列表
     *
     * @param sysUserDto 查询条件
     * @param pageQuery 分页参数
     * @return  用户列表
     */
    @ApiOperationSupport(order = 1)
    @ApiOperation(value = "获取用户列表")
    @SaCheckPermission("system:user:list")
    @GetMapping(value = "/list")
    public PageData<SysUserVo> list(SysUserDto sysUserDto, PageQuery pageQuery) {
        return sysUserService.selectPageUserList(sysUserDto, pageQuery);
    }

    /**
     * 根据部门获取用户列表
     *
     * @param sysUserDto 查询条件
     * @return  用户列表
     */
    @ApiOperationSupport(order = 4)
    @ApiOperation(value = "获取用户列表")
    @SaCheckPermission("system:user:list")
    @GetMapping(value = "/userList")
    public JsonResult<List<SysUserVo>> userList(SysUserDto sysUserDto ) {
        List<SysUserVo> sysUserVos = sysUserService.selectUserList(sysUserDto);
        return JsonResult.ok(sysUserVos);
    }

    /**
     * 导出用户(返回流)
     *
     * @param sysUserDto     用户对象
     * @param response 返回
     * @return 流
     */
    @ApiOperationSupport(order = 2)
    @ApiOperation(value = "导出用户(返回流)")
    @Log(title = "用户数据导出", businessType = BusinessType.EXPORT)
    @SaCheckPermission("system:user:export")
    @PostMapping(value = "/exportByStream", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
    public void exportByStream(SysUserDto sysUserDto, HttpServletResponse response) {
        List<SysUserVo> sysUserVos = sysUserService.selectUserList(sysUserDto);
        ExcelUtil.exportExcel(sysUserVos, "用户数据", SysUserVo.class, response);
    }

    /**
     * 用户导入
     *
     * @param file          文件
     * @param updateSupport 是否更新
     * @return
     * @throws Exception
     */
    @ApiOperationSupport(order = 3)
    @ApiOperation(value = "用户导入")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "file", value = "文件", dataType = "MultipartFile", dataTypeClass = MultipartFile.class, required = true),
            @ApiImplicitParam(name = "updateSupport", value = "是否更新", dataTypeClass = Boolean.class, required = true)
    })
    @Log(title = "用户导入", businessType = BusinessType.IMPORT)
    @SaCheckPermission("system:user:import")
    @PostMapping(value = "/importData")
    public JsonResult<Void> importData(@RequestPart MultipartFile file, boolean updateSupport) throws Exception {
        ExcelResult<SysUserImportVo> sysUserExcelResult = ExcelUtil.importExcel(file.getInputStream(),
                SysUserImportVo.class, new SysUserImportListener(updateSupport));
        return JsonResult.ok(sysUserExcelResult.getAnalysis());
    }

    /**
     * 根据用户编号获取详细信息
     */
    @ApiOperationSupport(order = 5)
    @ApiOperation(value = "根据用户编号获取详细信息")
    @ApiImplicitParam(name = "userId", value = "用户编号", dataTypeClass = Long.class)
    @SaCheckPermission("system:user:query")
    @GetMapping(value = {"/", "/{userId}"})
    public JsonResult<SysUserInfoVo> getInfo(@PathVariable(value = "userId", required = false) Long userId) {
        SysUserInfoVo userInfoVo = new SysUserInfoVo();
        SysRoleDto sysRoleDto = new SysRoleDto();
        sysRoleDto.setStatus(UserConstans.NORMAL);
        List<SysRoleVo> roles = sysRoleService.selectRoleList(sysRoleDto);
        //设置可选的用户角色，排除管理员
        userInfoVo.setRoles(LoginUtils.isAdmin(userId) ? roles : StreamUtils.filter(roles, r -> !r.isAdmin()));
        SysPostDto sysPostDto = new SysPostDto();
        sysRoleDto.setStatus(UserConstans.NORMAL);
        //设置可选的岗位
        userInfoVo.setPosts(sysPostService.selectPostList(sysPostDto));
        if (ObjectUtils.isNotNull(userId)) {
            SysUserVo sysUserVo = sysUserService.selectUserById(userId);
            SysUser sysUser = new SysUser();
            BeanUtils.copyProperties(sysUserVo, sysUser);
            userInfoVo.setData(sysUser);
            userInfoVo.setRoleIds(StreamUtils.toList(sysUserVo.getRoles(), SysRoleVo::getRoleId));
            userInfoVo.setPostIds(sysPostService.selectPostListByUserId(userId));
        }
        return JsonResult.ok(userInfoVo);
    }

    /**
     * 新增用户
     *
     * @param sysUserDto 用户信息
     * @return 结果
     */
    @ApiOperationSupport(order = 6)
    @ApiOperation(value = "新增用户")
    @SaCheckPermission("system:user:add")
    @Log(title = "新增用户", businessType = BusinessType.INSERT)
    @PostMapping
    public JsonResult<Void> add(@Validated(AddGroup.class) @RequestBody SysUserDto sysUserDto) {
        return sysUserService.saveUser(sysUserDto);
    }


    /**
     * 修改用户
     */
    @ApiOperationSupport(order = 7)
    @ApiOperation(value = "修改用户")
    @SaCheckPermission("system:user:edit")
    @Log(title = "用户管理", businessType = BusinessType.UPDATE)
    @PutMapping
    public JsonResult<Void> edit(@Validated(EditGroup.class) @RequestBody SysUserDto sysUserDto) {
        return sysUserService.editUser(sysUserDto);
    }

    /**
     * 批量删除用户
     */
    @ApiOperationSupport(order = 8)
    @ApiOperation(value = "批量删除用户")
    @ApiImplicitParam(name = "userIds", value = "用户ID数组", dataTypeClass = Long.class, allowMultiple = true, required = true)
    @SaCheckPermission("system:user:remove")
    @Log(title = "用户管理", businessType = BusinessType.DELETE)
    @DeleteMapping(value = "/{userIds}")
    public JsonResult<Void> remove(@PathVariable Long[] userIds) {
        if (ArrayUtils.contains(userIds, LoginUtils.getUserId())) {
            return JsonResult.fail("当前用户不能删除自己");
        }
        return toResult(sysUserService.deleteUserByIds(userIds));
    }

    /**
     * 重置密码
     */
    @ApiOperationSupport(order = 9)
    @ApiOperation(value = "重置密码")
    @SaCheckPermission("system:user:resetPwd")
    @Log(title = "重置密码", businessType = BusinessType.UPDATE)
    @PutMapping(value = "/resetPwd")
    public JsonResult<Void> resetPwd(@Validated(PasswordAuthGroup.class) @RequestBody SysUserDto sysUserDto) {
        return toResult(sysUserService.resetPwd(sysUserDto));
    }

    /**
     * 状态修改
     */
    @ApiOperationSupport(order = 10)
    @ApiOperation(value = "状态修改")
    @SaCheckPermission("system:user:edit")
    @Log(title = "状态修改", businessType = BusinessType.UPDATE)
    @PutMapping(value = "/changeStatus")
    public JsonResult<Void> changeStatus(@Validated(StatusGroup.class) @RequestBody SysUserDto sysUserDto) {
        return toResult(sysUserService.updateUserStatus(sysUserDto));
    }

}
